/**
 * Mixture of my stuff and stuff from the 216 book. Mostly mine.
 * 
 * Node:
 * Represents a node in an AVL Tree implementation of a Dictionary.
 */

public class Node<T> {
    private int leftHeight;
    private int rightHeight;
    private boolean isLeft = false, isRight = false;
    protected Node<T> left, right, parent;
    protected T key, element;
    
    /**
     * Constructor
     */
    Node (T k) {
        key = k;
        element = null;
        left = null;
        right = null;
        parent = null;
        this.setLeftHeight(0);
        this.setRightHeight(0);
    }
    Node (T k, T e) {
        key = k;
        element = e;
        left = null;
        right = null;
        parent = null;
        this.setLeftHeight(0);
        this.setRightHeight(0);
    }
    
    /**
     * Booleans
     */
    public boolean isLeaf () {
        return (left == null && right == null);
    }
    public boolean hasLeft () {
        return (left != null);
    }
    public boolean hasRight () {
        return (right != null);
    }
    public boolean isLeftChild () {
        return (isLeft);
    }
    public boolean isRightChild () {
        return (isRight);
    }
    
    /**
     * Getters
     */
    public int getBalance () {
        return (rightHeight - leftHeight);
    }
    public T getElement () {
        return element;
    }
    public T getKey () {
        return key;
    }
    public Node<T> getLeft () {
        return left;
    }
    public Node<T> getRight () {
        return right;
    }
    public int getLeftHeight () {
        return leftHeight;
    }
    public int getRightHeight () {
        return rightHeight;
    }
    public int getHeight () {
        return (Math.max(leftHeight,rightHeight));
    }
    public int getNumChildren () {
        int children = 0;
        
        if (left != null)
            children = 1 + left.getNumChildren();
        if (right != null)
            children = children + 1 + right.getNumChildren();
        
        return children;
    }
    public Node<T> getParent () {
        return parent;
    }
    
    /**
     * Setters
     */
    public void setLeft (Node<T> child) {
        left = child;
        if (child != null)
            child.setIsLeft();
    }
    public void setRight (Node<T> child) {
        right = child;
        if (child != null)
            child.setIsRight();
    }
    public void setIsLeft () {
        isLeft = true;
    }
    public void setIsRight () {
        isRight = true;
    }
    public void unsetIsLeft () {
        isLeft = false;
    }
    public void unsetIsRight () {
        isRight = false;
    }
    public void setLeftHeight (int h) {
        leftHeight = h;
    }
    public void setRightHeight (int h) {
        rightHeight = h;
    }
    public void setKey (T k) {
        key = k;
    }
    public void setElement (T e) {
        element = e;
    }
    public void setParent (Node<T> p) {
        parent = p;
    }
    
    /**
     * toString
     */
    public String toString () {
        return (key + " " + element);
    }
} // End Node
